library(ggplot2)
library(plotly)
library(ggmap)
library(sf)
library(dplyr)
library(leaflet)
library(htmlwidgets)
library(tmap)
library(sfheaders)
library(geojsonio)
Registered S3 method overwritten by 'geojsonsf':
  method        from   
  print.geojson geojson

Attaching package: ‘geojsonio’

The following object is masked from ‘package:base’:

    pretty
# Read the shapefile of Sydney suburbs
shp_path <- "/Users/LauraWu/Desktop/DATA5002 24T3/DATA5002 Project/GDA94/nsw_localities.shp"

syd <- st_read(shp_path)
Reading layer `nsw_localities' from data source 
  `/Users/LauraWu/Desktop/DATA5002 24T3/DATA5002 Project/GDA94/nsw_localities.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 4610 features and 6 fields
Geometry type: POLYGON
Dimension:     XY
Bounding box:  xmin: 140.9993 ymin: -37.50534 xmax: 159.1054 ymax: -28.15702
Geodetic CRS:  GDA94
# View column names and attribute data
# colnames(syd)
# head(syd)

Loading the dataset

airbnb <- read.csv("/Users/LauraWu/Desktop/DATA5002 24T3/DATA5002 Project/listings_summary_dec18.csv")

General picture

# General picture
suburb_listing_counts <- airbnb %>%
  group_by(city) %>%
  summarise(listings_count = n())

# Sort by number of listings (optional)
top_10_suburbs <- suburb_listing_counts %>%
  arrange(desc(listings_count)) %>%
   slice_head(n = 10)

# View the data
head(top_10_suburbs)
# Create the bar plot for the number of listings in each suburb
bar_plot <- ggplot(top_10_suburbs, aes(x = reorder(city, listings_count), y = listings_count)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  labs(title = "Top 10 the Number of Listings Suburbs", x = "Suburb", y = "Number of Listings") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  theme_minimal()

# Convert ggplot to plotly for interactivity
interactive_bar_plot <- ggplotly(bar_plot)
interactive_bar_plot
# Save the plot to an HTML file
htmlwidgets::saveWidget(interactive_bar_plot, "suburb_listing_bar_chart.html")
# clean NA values rows
syd_airbnb <- airbnb %>%
  filter(!is.na(price)) 

# Convert Airbnb data to spatial format
airbnb_sf <- st_as_sf(syd_airbnb, coords = c("longitude", "latitude"), crs = 4326)
airbnb_polygon <- airbnb_sf %>%
  group_by(id) %>% 
  summarise(geometry = st_union(geometry)) %>%
  st_convex_hull() 

View(airbnb_polygon)
# Perform spatial join
airbnb_polygon_tranformed <- st_transform(airbnb_polygon, crs = st_crs(syd))

airbnb_polygon_joined <- st_join(syd, airbnb_polygon_tranformed, join = st_intersects)

airbnb_with_suburbs <- airbnb_polygon_joined %>%
  filter(!is.na(id))

airbnb_with_suburbs_with_price <- merge(syd_airbnb, airbnb_with_suburbs, by = "id")
# Calculate price statistics per suburb
price_stats <- airbnb_with_suburbs_with_price %>%
  group_by(LOC_NAME) %>%
  summarise(
    avg_price = mean(price, na.rm = TRUE),
    min_price = min(price, na.rm = TRUE),
    max_price = max(price, na.rm = TRUE),
    median_price = median(price, na.rm = TRUE))
# filter for interactive plot
suburbs <- unique(airbnb_with_suburbs_with_price$LOC_NAME)

# Create an initial plot with traces for each suburb
price_suburbs <- plot_ly()

for (suburb in suburbs) {
  price_suburbs <- price_suburbs %>%
    add_trace(
      data = filter(airbnb_with_suburbs_with_price, LOC_NAME == suburb),
      x = ~LOC_NAME,
      y = ~price,
      type = "box",
      name = suburb,
      visible = FALSE
    )
}

# Add a default trace (e.g., All Suburbs)
price_suburbs <- price_suburbs %>%
  add_trace(
    data = airbnb_with_suburbs_with_price,
    x = ~LOC_NAME,
    y = ~price,
    type = "box",
    name = "All Suburbs",
    visible = TRUE
  )

# Define dropdown buttons
buttons <- list(
  list(
    label = "All Suburbs",
    method = "update",
    args = list(list(visible = c(rep(FALSE, length(suburbs)), TRUE)), 
                list(title = "Price Distribution: All Suburbs"))
  )
)

# Add buttons for each suburb
for (i in seq_along(suburbs)) {
  buttons <- append(buttons, list(
    list(
      label = suburbs[i],
      method = "update",
      args = list(list(visible = c(rep(FALSE, i - 1), TRUE, rep(FALSE, length(suburbs) - i), FALSE)),
                  list(title = paste("Price Distribution:", suburbs[i])))
    )
  ))
}

# Add layout with dropdown
price_suburbs <- price_suburbs %>%
  layout(
    title = "Price Distribution Across Suburbs",
    xaxis = list(title = "Suburb", tickangle = 45),
    yaxis = list(title = "Price ($)"),
    updatemenus = list(
      list(
        type = "dropdown",
        x = 0.1, y = 1.2,
        buttons = buttons
      )
    )
  )

# Display the plot
price_suburbs
# Average price by suburbs
price_avg_suburbs <- airbnb_with_suburbs_with_price %>%
  group_by(LOC_NAME) %>%
  summarise(avg_price = mean(price, na.rm = TRUE))%>%
  filter(!is.na(avg_price))

syd_price_avg_suburbs <- syd %>%
  left_join(price_avg_suburbs, by = c("LOC_NAME" = "LOC_NAME")) %>%
  filter(!is.na(avg_price)) 

suburbs <- unique(airbnb_with_suburbs_with_price$LOC_NAME)

# Create an initial plot with choropleth traces for each suburb
price_suburbs_map <- plot_ly()

# Iterate over suburbs to create choropleth traces
for (suburb in suburbs) {
  price_suburbs_map <- price_suburbs_map %>%
    add_trace(syd_price_avg_suburbs,
      type = "choropleth",
      locations = ~LOC_NAME,
      z = ~avg_price,  # Replace with the column for average price
      hoverinfo = "location+z",  # Display both location and value
      color = ~avg_price,  # Color based on average price
      colorscale = "YlOrRd",  # Color scale
      name = suburb,
      visible = FALSE,  # Set all traces as hidden by default
      colorbar = list(title = "Avg Price", ticks = "outside")
    )
}

# Add a default trace (e.g., All Suburbs)
price_suburbs_map <- price_suburbs_map %>%
  add_trace(syd_price_avg_suburbs,
    type = "choropleth",
    locations = ~LOC_NAME,
    z = ~avg_price,
    hoverinfo = "location+z",
    color = ~avg_price,
    colorscale = "YlOrRd",
    name = "All Suburbs",
    visible = TRUE,
    colorbar = list(title = "Avg Price", ticks = "outside")
  )

# Define dropdown buttons for each suburb
buttons <- list(
  list(
    label = "All Suburbs",
    method = "update",
    args = list(list(visible = c(rep(FALSE, length(suburbs)), TRUE)), 
                list(title = "Price Distribution: All Suburbs"))
  )
)

# Add buttons for each suburb
for (i in seq_along(suburbs)) {
  buttons <- append(buttons, list(
    list(
      label = suburbs[i],
      method = "update",
      args = list(list(visible = c(rep(FALSE, i - 1), TRUE, rep(FALSE, length(suburbs) - i), FALSE)),
                  list(title = paste("Price Distribution:", suburbs[i])))
    )
  ))
}

# Add layout with dropdown menu and customize the map appearance
price_suburbs_map <- price_suburbs_map %>%
  layout(
    geo = list(
      showlakes = TRUE,
      lakecolor = 'white',
      projection = list(type = 'mercator'),
      scope = 'world',  # You can set this to a specific region if needed
      visible = TRUE
    ),
    title = "Price Distribution Across Suburbs",
    updatemenus = list(
      list(
        type = "dropdown",
        x = 0.1, y = 1.2,
        buttons = buttons
      )
    )
  )

# Display the map
price_suburbs_map
Error in eval(expr, data, expr_env) : object 'LOC_NAME' not found
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQogCgoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwbG90bHkpCmxpYnJhcnkoZ2dtYXApCmxpYnJhcnkoc2YpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkobGVhZmxldCkKbGlicmFyeShodG1sd2lkZ2V0cykKbGlicmFyeSh0bWFwKQpsaWJyYXJ5KHNmaGVhZGVycykKbGlicmFyeShnZW9qc29uaW8pCmBgYAoKCmBgYHtyfQojIFJlYWQgdGhlIHNoYXBlZmlsZSBvZiBTeWRuZXkgc3VidXJicwpzaHBfcGF0aCA8LSAiL1VzZXJzL0xhdXJhV3UvRGVza3RvcC9EQVRBNTAwMiAyNFQzL0RBVEE1MDAyIFByb2plY3QvR0RBOTQvbnN3X2xvY2FsaXRpZXMuc2hwIgoKc3lkIDwtIHN0X3JlYWQoc2hwX3BhdGgpCgojIFZpZXcgY29sdW1uIG5hbWVzIGFuZCBhdHRyaWJ1dGUgZGF0YQojIGNvbG5hbWVzKHN5ZCkKIyBoZWFkKHN5ZCkKYGBgCgoqKkxvYWRpbmcgdGhlIGRhdGFzZXQqKgpgYGB7cn0KYWlyYm5iIDwtIHJlYWQuY3N2KCIvVXNlcnMvTGF1cmFXdS9EZXNrdG9wL0RBVEE1MDAyIDI0VDMvREFUQTUwMDIgUHJvamVjdC9saXN0aW5nc19zdW1tYXJ5X2RlYzE4LmNzdiIpCmBgYAoKCioqR2VuZXJhbCBwaWN0dXJlKioKCi0gVG9wIDEwIG51bWJlciBvZiBsaXN0aW5ncyBTdWJ1cmJzCmBgYHtyfQojIEdlbmVyYWwgcGljdHVyZQpzdWJ1cmJfbGlzdGluZ19jb3VudHMgPC0gYWlyYm5iICU+JQogIGdyb3VwX2J5KGNpdHkpICU+JQogIHN1bW1hcmlzZShsaXN0aW5nc19jb3VudCA9IG4oKSkKCiMgU29ydCBieSBudW1iZXIgb2YgbGlzdGluZ3MgKG9wdGlvbmFsKQp0b3BfMTBfc3VidXJicyA8LSBzdWJ1cmJfbGlzdGluZ19jb3VudHMgJT4lCiAgYXJyYW5nZShkZXNjKGxpc3RpbmdzX2NvdW50KSkgJT4lCiAgIHNsaWNlX2hlYWQobiA9IDEwKQoKIyBWaWV3IHRoZSBkYXRhCmhlYWQodG9wXzEwX3N1YnVyYnMpCmBgYApgYGB7cn0KIyBDcmVhdGUgdGhlIGJhciBwbG90IGZvciB0aGUgbnVtYmVyIG9mIGxpc3RpbmdzIGluIGVhY2ggc3VidXJiCmJhcl9wbG90IDwtIGdncGxvdCh0b3BfMTBfc3VidXJicywgYWVzKHggPSByZW9yZGVyKGNpdHksIGxpc3RpbmdzX2NvdW50KSwgeSA9IGxpc3RpbmdzX2NvdW50KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gInN0ZWVsYmx1ZSIpICsKICBsYWJzKHRpdGxlID0gIlRvcCAxMCB0aGUgTnVtYmVyIG9mIExpc3RpbmdzIFN1YnVyYnMiLCB4ID0gIlN1YnVyYiIsIHkgPSAiTnVtYmVyIG9mIExpc3RpbmdzIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICB0aGVtZV9taW5pbWFsKCkKCiMgQ29udmVydCBnZ3Bsb3QgdG8gcGxvdGx5IGZvciBpbnRlcmFjdGl2aXR5CmludGVyYWN0aXZlX2Jhcl9wbG90IDwtIGdncGxvdGx5KGJhcl9wbG90KQppbnRlcmFjdGl2ZV9iYXJfcGxvdAojIFNhdmUgdGhlIHBsb3QgdG8gYW4gSFRNTCBmaWxlCmh0bWx3aWRnZXRzOjpzYXZlV2lkZ2V0KGludGVyYWN0aXZlX2Jhcl9wbG90LCAic3VidXJiX2xpc3RpbmdfYmFyX2NoYXJ0Lmh0bWwiKQoKYGBgCgoKYGBge3J9CgpgYGAKCmBgYHtyfQojIGNsZWFuIE5BIHZhbHVlcyByb3dzCnN5ZF9haXJibmIgPC0gYWlyYm5iICU+JQogIGZpbHRlcighaXMubmEocHJpY2UpKSAKCiMgQ29udmVydCBBaXJibmIgZGF0YSB0byBzcGF0aWFsIGZvcm1hdAphaXJibmJfc2YgPC0gc3RfYXNfc2Yoc3lkX2FpcmJuYiwgY29vcmRzID0gYygibG9uZ2l0dWRlIiwgImxhdGl0dWRlIiksIGNycyA9IDQzMjYpCmBgYAoKYGBge3J9CmFpcmJuYl9wb2x5Z29uIDwtIGFpcmJuYl9zZiAlPiUKICBncm91cF9ieShpZCkgJT4lIAogIHN1bW1hcmlzZShnZW9tZXRyeSA9IHN0X3VuaW9uKGdlb21ldHJ5KSkgJT4lCiAgc3RfY29udmV4X2h1bGwoKSAKCmBgYAoKYGBge3J9CiMgUGVyZm9ybSBzcGF0aWFsIGpvaW4KYWlyYm5iX3BvbHlnb25fdHJhbmZvcm1lZCA8LSBzdF90cmFuc2Zvcm0oYWlyYm5iX3BvbHlnb24sIGNycyA9IHN0X2NycyhzeWQpKQoKYWlyYm5iX3BvbHlnb25fam9pbmVkIDwtIHN0X2pvaW4oc3lkLCBhaXJibmJfcG9seWdvbl90cmFuZm9ybWVkLCBqb2luID0gc3RfaW50ZXJzZWN0cykKCmFpcmJuYl93aXRoX3N1YnVyYnMgPC0gYWlyYm5iX3BvbHlnb25fam9pbmVkICU+JQogIGZpbHRlcighaXMubmEoaWQpKQoKYWlyYm5iX3dpdGhfc3VidXJic193aXRoX3ByaWNlIDwtIG1lcmdlKHN5ZF9haXJibmIsIGFpcmJuYl93aXRoX3N1YnVyYnMsIGJ5ID0gImlkIikKYGBgCgpgYGB7cn0KIyBDYWxjdWxhdGUgcHJpY2Ugc3RhdGlzdGljcyBwZXIgc3VidXJiCnByaWNlX3N0YXRzIDwtIGFpcmJuYl93aXRoX3N1YnVyYnNfd2l0aF9wcmljZSAlPiUKICBncm91cF9ieShMT0NfTkFNRSkgJT4lCiAgc3VtbWFyaXNlKAogICAgYXZnX3ByaWNlID0gbWVhbihwcmljZSwgbmEucm0gPSBUUlVFKSwKICAgIG1pbl9wcmljZSA9IG1pbihwcmljZSwgbmEucm0gPSBUUlVFKSwKICAgIG1heF9wcmljZSA9IG1heChwcmljZSwgbmEucm0gPSBUUlVFKSwKICAgIG1lZGlhbl9wcmljZSA9IG1lZGlhbihwcmljZSwgbmEucm0gPSBUUlVFKSkKYGBgCgpgYGB7cn0KIyBmaWx0ZXIgZm9yIGludGVyYWN0aXZlIHBsb3QKc3VidXJicyA8LSB1bmlxdWUoYWlyYm5iX3dpdGhfc3VidXJic193aXRoX3ByaWNlJExPQ19OQU1FKQoKIyBDcmVhdGUgYW4gaW5pdGlhbCBwbG90IHdpdGggdHJhY2VzIGZvciBlYWNoIHN1YnVyYgpwcmljZV9zdWJ1cmJzIDwtIHBsb3RfbHkoKQoKZm9yIChzdWJ1cmIgaW4gc3VidXJicykgewogIHByaWNlX3N1YnVyYnMgPC0gcHJpY2Vfc3VidXJicyAlPiUKICAgIGFkZF90cmFjZSgKICAgICAgZGF0YSA9IGZpbHRlcihhaXJibmJfd2l0aF9zdWJ1cmJzX3dpdGhfcHJpY2UsIExPQ19OQU1FID09IHN1YnVyYiksCiAgICAgIHggPSB+TE9DX05BTUUsCiAgICAgIHkgPSB+cHJpY2UsCiAgICAgIHR5cGUgPSAiYm94IiwKICAgICAgbmFtZSA9IHN1YnVyYiwKICAgICAgdmlzaWJsZSA9IEZBTFNFCiAgICApCn0KCiMgQWRkIGEgZGVmYXVsdCB0cmFjZSAoZS5nLiwgQWxsIFN1YnVyYnMpCnByaWNlX3N1YnVyYnMgPC0gcHJpY2Vfc3VidXJicyAlPiUKICBhZGRfdHJhY2UoCiAgICBkYXRhID0gYWlyYm5iX3dpdGhfc3VidXJic193aXRoX3ByaWNlLAogICAgeCA9IH5MT0NfTkFNRSwKICAgIHkgPSB+cHJpY2UsCiAgICB0eXBlID0gImJveCIsCiAgICBuYW1lID0gIkFsbCBTdWJ1cmJzIiwKICAgIHZpc2libGUgPSBUUlVFCiAgKQoKIyBEZWZpbmUgZHJvcGRvd24gYnV0dG9ucwpidXR0b25zIDwtIGxpc3QoCiAgbGlzdCgKICAgIGxhYmVsID0gIkFsbCBTdWJ1cmJzIiwKICAgIG1ldGhvZCA9ICJ1cGRhdGUiLAogICAgYXJncyA9IGxpc3QobGlzdCh2aXNpYmxlID0gYyhyZXAoRkFMU0UsIGxlbmd0aChzdWJ1cmJzKSksIFRSVUUpKSwgCiAgICAgICAgICAgICAgICBsaXN0KHRpdGxlID0gIlByaWNlIERpc3RyaWJ1dGlvbjogQWxsIFN1YnVyYnMiKSkKICApCikKCiMgQWRkIGJ1dHRvbnMgZm9yIGVhY2ggc3VidXJiCmZvciAoaSBpbiBzZXFfYWxvbmcoc3VidXJicykpIHsKICBidXR0b25zIDwtIGFwcGVuZChidXR0b25zLCBsaXN0KAogICAgbGlzdCgKICAgICAgbGFiZWwgPSBzdWJ1cmJzW2ldLAogICAgICBtZXRob2QgPSAidXBkYXRlIiwKICAgICAgYXJncyA9IGxpc3QobGlzdCh2aXNpYmxlID0gYyhyZXAoRkFMU0UsIGkgLSAxKSwgVFJVRSwgcmVwKEZBTFNFLCBsZW5ndGgoc3VidXJicykgLSBpKSwgRkFMU0UpKSwKICAgICAgICAgICAgICAgICAgbGlzdCh0aXRsZSA9IHBhc3RlKCJQcmljZSBEaXN0cmlidXRpb246Iiwgc3VidXJic1tpXSkpKQogICAgKQogICkpCn0KCiMgQWRkIGxheW91dCB3aXRoIGRyb3Bkb3duCnByaWNlX3N1YnVyYnMgPC0gcHJpY2Vfc3VidXJicyAlPiUKICBsYXlvdXQoCiAgICB0aXRsZSA9ICJQcmljZSBEaXN0cmlidXRpb24gQWNyb3NzIFN1YnVyYnMiLAogICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIlN1YnVyYiIsIHRpY2thbmdsZSA9IDQ1KSwKICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJQcmljZSAoJCkiKSwKICAgIHVwZGF0ZW1lbnVzID0gbGlzdCgKICAgICAgbGlzdCgKICAgICAgICB0eXBlID0gImRyb3Bkb3duIiwKICAgICAgICB4ID0gMC4xLCB5ID0gMS4yLAogICAgICAgIGJ1dHRvbnMgPSBidXR0b25zCiAgICAgICkKICAgICkKICApCgojIERpc3BsYXkgdGhlIHBsb3QKcHJpY2Vfc3VidXJicwpgYGAKCgpgYGB7cn0KIyBBdmVyYWdlIHByaWNlIGJ5IHN1YnVyYnMKcHJpY2VfYXZnX3N1YnVyYnMgPC0gYWlyYm5iX3dpdGhfc3VidXJic193aXRoX3ByaWNlICU+JQogIGdyb3VwX2J5KExPQ19OQU1FKSAlPiUKICBzdW1tYXJpc2UoYXZnX3ByaWNlID0gbWVhbihwcmljZSwgbmEucm0gPSBUUlVFKSklPiUKICBmaWx0ZXIoIWlzLm5hKGF2Z19wcmljZSkpCgpzeWRfcHJpY2VfYXZnX3N1YnVyYnMgPC0gc3lkICU+JQogIGxlZnRfam9pbihwcmljZV9hdmdfc3VidXJicywgYnkgPSBjKCJMT0NfTkFNRSIgPSAiTE9DX05BTUUiKSkgJT4lCiAgZmlsdGVyKCFpcy5uYShhdmdfcHJpY2UpKSAKCnN1YnVyYnMgPC0gdW5pcXVlKGFpcmJuYl93aXRoX3N1YnVyYnNfd2l0aF9wcmljZSRMT0NfTkFNRSkKCiMgQ3JlYXRlIGFuIGluaXRpYWwgcGxvdCB3aXRoIGNob3JvcGxldGggdHJhY2VzIGZvciBlYWNoIHN1YnVyYgpwcmljZV9zdWJ1cmJzX21hcCA8LSBwbG90X2x5KCkKCiMgSXRlcmF0ZSBvdmVyIHN1YnVyYnMgdG8gY3JlYXRlIGNob3JvcGxldGggdHJhY2VzCmZvciAoc3VidXJiIGluIHN1YnVyYnMpIHsKICBwcmljZV9zdWJ1cmJzX21hcCA8LSBwcmljZV9zdWJ1cmJzX21hcCAlPiUKICAgIGFkZF90cmFjZShzeWRfcHJpY2VfYXZnX3N1YnVyYnMsCiAgICAgIHR5cGUgPSAiY2hvcm9wbGV0aCIsCiAgICAgIGxvY2F0aW9ucyA9IH5MT0NfTkFNRSwKICAgICAgeiA9IH5hdmdfcHJpY2UsICAjIFJlcGxhY2Ugd2l0aCB0aGUgY29sdW1uIGZvciBhdmVyYWdlIHByaWNlCiAgICAgIGhvdmVyaW5mbyA9ICJsb2NhdGlvbit6IiwgICMgRGlzcGxheSBib3RoIGxvY2F0aW9uIGFuZCB2YWx1ZQogICAgICBjb2xvciA9IH5hdmdfcHJpY2UsICAjIENvbG9yIGJhc2VkIG9uIGF2ZXJhZ2UgcHJpY2UKICAgICAgY29sb3JzY2FsZSA9ICJZbE9yUmQiLCAgIyBDb2xvciBzY2FsZQogICAgICBuYW1lID0gc3VidXJiLAogICAgICB2aXNpYmxlID0gRkFMU0UsICAjIFNldCBhbGwgdHJhY2VzIGFzIGhpZGRlbiBieSBkZWZhdWx0CiAgICAgIGNvbG9yYmFyID0gbGlzdCh0aXRsZSA9ICJBdmcgUHJpY2UiLCB0aWNrcyA9ICJvdXRzaWRlIikKICAgICkKfQoKIyBBZGQgYSBkZWZhdWx0IHRyYWNlIChlLmcuLCBBbGwgU3VidXJicykKcHJpY2Vfc3VidXJic19tYXAgPC0gcHJpY2Vfc3VidXJic19tYXAgJT4lCiAgYWRkX3RyYWNlKHN5ZF9wcmljZV9hdmdfc3VidXJicywKICAgIHR5cGUgPSAiY2hvcm9wbGV0aCIsCiAgICBsb2NhdGlvbnMgPSB+TE9DX05BTUUsCiAgICB6ID0gfmF2Z19wcmljZSwKICAgIGhvdmVyaW5mbyA9ICJsb2NhdGlvbit6IiwKICAgIGNvbG9yID0gfmF2Z19wcmljZSwKICAgIGNvbG9yc2NhbGUgPSAiWWxPclJkIiwKICAgIG5hbWUgPSAiQWxsIFN1YnVyYnMiLAogICAgdmlzaWJsZSA9IFRSVUUsCiAgICBjb2xvcmJhciA9IGxpc3QodGl0bGUgPSAiQXZnIFByaWNlIiwgdGlja3MgPSAib3V0c2lkZSIpCiAgKQoKIyBEZWZpbmUgZHJvcGRvd24gYnV0dG9ucyBmb3IgZWFjaCBzdWJ1cmIKYnV0dG9ucyA8LSBsaXN0KAogIGxpc3QoCiAgICBsYWJlbCA9ICJBbGwgU3VidXJicyIsCiAgICBtZXRob2QgPSAidXBkYXRlIiwKICAgIGFyZ3MgPSBsaXN0KGxpc3QodmlzaWJsZSA9IGMocmVwKEZBTFNFLCBsZW5ndGgoc3VidXJicykpLCBUUlVFKSksIAogICAgICAgICAgICAgICAgbGlzdCh0aXRsZSA9ICJQcmljZSBEaXN0cmlidXRpb246IEFsbCBTdWJ1cmJzIikpCiAgKQopCgojIEFkZCBidXR0b25zIGZvciBlYWNoIHN1YnVyYgpmb3IgKGkgaW4gc2VxX2Fsb25nKHN1YnVyYnMpKSB7CiAgYnV0dG9ucyA8LSBhcHBlbmQoYnV0dG9ucywgbGlzdCgKICAgIGxpc3QoCiAgICAgIGxhYmVsID0gc3VidXJic1tpXSwKICAgICAgbWV0aG9kID0gInVwZGF0ZSIsCiAgICAgIGFyZ3MgPSBsaXN0KGxpc3QodmlzaWJsZSA9IGMocmVwKEZBTFNFLCBpIC0gMSksIFRSVUUsIHJlcChGQUxTRSwgbGVuZ3RoKHN1YnVyYnMpIC0gaSksIEZBTFNFKSksCiAgICAgICAgICAgICAgICAgIGxpc3QodGl0bGUgPSBwYXN0ZSgiUHJpY2UgRGlzdHJpYnV0aW9uOiIsIHN1YnVyYnNbaV0pKSkKICAgICkKICApKQp9CgojIEFkZCBsYXlvdXQgd2l0aCBkcm9wZG93biBtZW51IGFuZCBjdXN0b21pemUgdGhlIG1hcCBhcHBlYXJhbmNlCnByaWNlX3N1YnVyYnNfbWFwIDwtIHByaWNlX3N1YnVyYnNfbWFwICU+JQogIGxheW91dCgKICAgIGdlbyA9IGxpc3QoCiAgICAgIHNob3dsYWtlcyA9IFRSVUUsCiAgICAgIGxha2Vjb2xvciA9ICd3aGl0ZScsCiAgICAgIHByb2plY3Rpb24gPSBsaXN0KHR5cGUgPSAnbWVyY2F0b3InKSwKICAgICAgc2NvcGUgPSAnd29ybGQnLCAgIyBZb3UgY2FuIHNldCB0aGlzIHRvIGEgc3BlY2lmaWMgcmVnaW9uIGlmIG5lZWRlZAogICAgICB2aXNpYmxlID0gVFJVRQogICAgKSwKICAgIHRpdGxlID0gIlByaWNlIERpc3RyaWJ1dGlvbiBBY3Jvc3MgU3VidXJicyIsCiAgICB1cGRhdGVtZW51cyA9IGxpc3QoCiAgICAgIGxpc3QoCiAgICAgICAgdHlwZSA9ICJkcm9wZG93biIsCiAgICAgICAgeCA9IDAuMSwgeSA9IDEuMiwKICAgICAgICBidXR0b25zID0gYnV0dG9ucwogICAgICApCiAgICApCiAgKQoKIyBEaXNwbGF5IHRoZSBtYXAKcHJpY2Vfc3VidXJic19tYXAKYGBgCgoKCgoKCgoKCgoKCgoK